#include "fullscritem.h"

#include "AEE.h"
#include "AEEImageWidget.h"
#include "AEEPropContainer.h"
#include "dfon_comdef.h"
#include "node.h"

typedef struct FullscrItem
{
	IPropContainer *propContainer;
	IWidget *rightArrowWidget;
	IWidget *leftArrowWidget;
	IWidget *imageWidget;
	IModel *model;
	ModelListener mdlListener;
	HandlerDesc hdesc;
	IImage *busyImage;
	IImage *brokenImage;
	IImage *imageToShow;
	IShell *shell;
} FullscrItem ;

static void ImageLoaded(void *data, IImage * po, AEEImageInfo * pi, int nErr)
{
	FullscrItem *me = data;


	if(po && pi && nErr == SUCCESS){
		AEERect r;
		IWIDGET_GetClientRect(me->imageWidget, &r);

		//set scale if needed
		if(pi->cx > r.dx || pi->cy>r.dy)
		{
			double xRatio = pi->cx / (double)r.dx;
			double yRatio = pi->cy / (double)r.dy;
			double ratio = MAX(yRatio, xRatio);
			IImage_SetParm(po, IPARM_SCALE, (int)(pi->cx/ratio), (int)(pi->cy/ratio));
		}

		IWIDGET_SetImage(me->imageWidget, me->imageToShow);
	}else{
		IWIDGET_SetImage(me->imageWidget, me->brokenImage);
		RELEASEIF(me->imageToShow);
	}
}

static void OnModelEvent(void *userData, ModelEvent *event)
{
	FullscrItem *me = userData;

	if(event->evCode == EVT_MDL_VALUE)
	{
		NodeFile *node = IVALUEMODEL_GetValue((IValueModel*)event->pModel, NULL);
		if(node && node->base.type == NodeTypeFile)
		{
			if(me->imageToShow){
				IImage_Notify(me->imageToShow, NULL, NULL);
				RELEASEIF(me->imageToShow);
			}
			IWIDGET_SetImage(me->imageWidget, me->busyImage);
			me->imageToShow = ISHELL_LoadImage(me->shell, node->fi.szName);
			if(!me->imageToShow){
				IWIDGET_SetImage(me->imageWidget, me->brokenImage);
			}else{
				IImage_Notify(me->imageToShow, ImageLoaded, me);
			}
		}
	}
}

static void FullscrItem_Free(void *data)
{
	FullscrItem *me = data;
	LISTENER_Cancel(&me->mdlListener);
	RELEASEIF(me->imageToShow);
	RELEASEIF(me->brokenImage);
	RELEASEIF(me->busyImage);
	RELEASEIF(me->model);
	RELEASEIF(me->rightArrowWidget);
	RELEASEIF(me->leftArrowWidget);
	RELEASEIF(me->imageWidget);
	HANDLERDESC_Free(&me->hdesc);
	FREEIF(data);
}

static void FullscrItem_HandleEvent(void *data, AEEEvent evt, uint16 wParam, uint32 dwParam)
{
	FullscrItem *me = data;

	if(evt == EVT_WDG_SETPROPERTY && wParam == PROP_RIGHT_ARROW){
		IWIDGET_SetImage(me->rightArrowWidget, (IImage*)dwParam);
	}else if(evt == EVT_WDG_SETPROPERTY && wParam == PROP_LEFT_ARROW){
		IWIDGET_SetImage(me->leftArrowWidget, (IImage*)dwParam);
	}else if(evt == EVT_WDG_SETPROPERTY){
		IWIDGET_HandleEvent(me->imageWidget, evt, wParam, dwParam);
	}

	HANDLERDESC_Call(&me->hdesc, evt, wParam, dwParam);
}

int FullscrItem_New(IWidget** ppo, IShell *shell)
{
	WidgetProp arrowsProp = {WIDGET_SIZE_TO_FIT, TRUE};
	WidgetProp imageProp = {1, TRUE};
	int retval = SUCCESS;
	FullscrItem *me = MALLOCREC(FullscrItem);
	IWidget *containerWidget = NULL;

	if(!me)
		return ENOMEMORY;

	ISHELL_CreateInstance(shell, AEECLSID_PROPCONTAINER, (void**)&me->propContainer);
	ISHELL_CreateInstance(shell, AEECLSID_VALUEMODEL, (void**)&me->model);
	ISHELL_CreateInstance(shell, AEECLSID_IMAGEWIDGET, (void**)&me->imageWidget);
	ISHELL_CreateInstance(shell, AEECLSID_IMAGEWIDGET, (void**)&me->rightArrowWidget);
	ISHELL_CreateInstance(shell, AEECLSID_IMAGEWIDGET, (void**)&me->leftArrowWidget);
	IPROPCONTAINER_QueryInterface(me->propContainer, AEEIID_WIDGET, (void**)&containerWidget);
	if(!me->model || !me->propContainer || !me->imageWidget || !containerWidget)
	{
		retval = ENOMEMORY;
		goto cleanup;
	}

	me->shell = shell;
	me->brokenImage = ISHELL_LoadBusyImage(shell);
	me->busyImage = ISHELL_LoadBusyImage(shell);
	IWIDGET_SetFlags(me->imageWidget, IDF_ALIGN_CENTER|IDF_ALIGN_MIDDLE);
	IWIDGET_SetFlags(me->rightArrowWidget, IDF_ALIGN_CENTER|IDF_ALIGN_MIDDLE);
	IWIDGET_SetFlags(me->leftArrowWidget, IDF_ALIGN_CENTER|IDF_ALIGN_MIDDLE);
	IWIDGET_SetModel(containerWidget, me->model);
	HANDLERDESC_Init(&me->hdesc, FullscrItem_HandleEvent, me, FullscrItem_Free);
	IWIDGET_SetHandler(containerWidget, &me->hdesc);
	IMODEL_AddListenerEx(me->model, &me->mdlListener, OnModelEvent, me);
	IWIDGET_SetLayoutStyle(containerWidget, LAYOUT_HORZ);
	IPROPCONTAINER_Insert(me->propContainer, me->leftArrowWidget, WIDGET_ZNORMAL, &arrowsProp);
	IPROPCONTAINER_Insert(me->propContainer, me->imageWidget, WIDGET_ZNORMAL, &imageProp);
	IPROPCONTAINER_Insert(me->propContainer, me->rightArrowWidget, WIDGET_ZNORMAL, &arrowsProp);

	*ppo = containerWidget;

cleanup:
	if(retval != SUCCESS)
		FullscrItem_Free(me);
	RELEASEIF(containerWidget);
	return retval;
}